package cs2114.alarmclock;

/**
 * // -------------------------------------------------------------------------
/**
 *  Smart link class that uses "join" and "split" methods to make implementing
 *  Abstract Data Types that are built based on Linked Lists much easier to
 *  implement.
 *
 *  @author Joe Acanfora
 *  @version Nov 12, 2011
 *  @param <Item>
 */
public class Link<Item>
{
//-----------------Fields-------------------------------------
    /**
     * The data stored in the link.
     */
    private Item data;
    /**
     * The Link that follows this link.
     */
    private Link<Item> next;
    /**
     * The link that preceeds this link.
     */
    private Link<Item> previous;


    /**
     * Constructor for the Link<Item> Object.
     * @param info  the data to be stored.
     */
    public Link(Item info)
    {
        this.data = info;
    }
//-----------------------Methods----------------------------
    /**
     * Getter method for the data in this link.
     * @return Item the data stored in this link.
     */
    public Item getData()
    {
        return this.data;
    }

    /**
     * Set the data into the link.
     * @param value  the data to be placed into the link.
     */
    public void setData(Item value)
    {
        data = value;
    }
//    /**
//     * Set the next element in the LinkedList.
//     * @param nextLink  the nextLink in the LinkedList
//     */
//    public void setNext(Link<Item> nextLink)
//    {
//        next = nextLink;
//    }
    /**
     * Getter method for the Link following this Link.
     * @return Link<Item> the Link following this Link.
     */
    public Link<Item> next()
    {
        return this.next;
    }
    /**
     * Getter method for the link that preceeds this Link.
     * @return Link<Item> the link that preceeds this link.
     */
    public Link<Item> previous()
    {
        return this.previous;
    }
    /**
     * Connects the specified link as the follower of the receiver.
     *
     * @precondition The receiver must not already have a link following it.
     * @precondition The follower must not already have a link preceding it.
     *
     * @param follower the Link that should follow the receiver
     * @return the receiver
     */
    public Link<Item> join(Link<Item> follower)
    {
        assert this.next == null :
            "There is already a link following this link.";
        assert follower.previous == null :
            "There is already a link joined to the follower.";

        this.next = follower;
        follower.previous = this;

        return this;
    }

    /**
     * Disconnects the link between receiver and its follower and returns the
     * follower.
     *
     * @return the old follower of the receiver, or null if the receiver had
     *     no follower
     */
    public Link<Item> split()
    {
        Link<Item> oldFollower = next;

        this.next = null;

        if (oldFollower != null)
        {
            oldFollower.previous = null;
        }

        return oldFollower;
    }

}
